import pandas as pd
import pyecharts.options as opts
from pyecharts.charts import HeatMap,Scatter,Pie,Bar
from pyecharts.charts import Bar,Timeline
from pyecharts.options import LabelOpts,TitleOpts
from pyecharts.globals import ThemeType


df = pd.read_csv("data\order.csv") 

# 数据特征分析

# 因为数据量比较大所以对数据做简单的清洗
# 订单号一般都是唯一的，所以对订单号进行查重
df.drop_duplicates(subset=['order'],inplace=True)
# 查看数据类型
print(df.dtypes)
# 数据描述性统计查看
print(df.describe())
# 查看折扣率小于0的,并进行降序排序
df.loc[df['discount%'] < 0,:].sort_values(by='discount%', ascending=True).head(10)
# 查看空值
df.isnull().sum()
# 使用drop_duplicates()查重
df.drop_duplicates(subset=['order'])



# 1、客户购物时间分析
# 探索客户下单时间的分布情况，可以进行分组分析
group_time = df.groupby(by=['hour','weekday'])['order'].count()
group_time

# 热力图横轴、纵轴数据构造
x_list = [str(i+1) for i in range(24)]
y_list = ['周一','周二','周三','周四','周五','周六','周天']
# 热力图数据构造
hour_list = [i+1 for i in range(24)]
day_list = [i+1 for i in range(7)]
value_list = []
for i in range(len(hour_list)):
    for j in range(len(day_list)):
        try:
            value_list.append([i,j,int(group_time[i,day_list[j]])])     # 因为考虑到分组分析中无对应索引,所以会报错
        except Exception as e:
#             print(e)
            value_list.append([i,j,0])      # 无对应索引的值赋值为0
print(value_list)
# 画热力图，并将热力图保存到tmp文件夹中
c = (
    HeatMap(init_opts=opts.InitOpts(width="800px", height="400px"))
    .add_xaxis(xaxis_data=x_list)
    .add_yaxis(
        series_name="下单人数",
        yaxis_data=y_list,
        value=value_list,
        label_opts=opts.LabelOpts(
                                is_show=True, 
                                color="#fff", 
                                position="inside", 
        ),
    )
    .set_global_opts(
        legend_opts=opts.LegendOpts(is_show=False),
        xaxis_opts=opts.AxisOpts(
            type_="category",
            splitarea_opts=opts.SplitAreaOpts(
                is_show=True, areastyle_opts=opts.AreaStyleOpts(opacity=1)  # opacity 网格线的透明度
            ),
        ),
        yaxis_opts=opts.AxisOpts(
            type_="category",
            splitarea_opts=opts.SplitAreaOpts(
                is_show=True, areastyle_opts=opts.AreaStyleOpts(opacity=1)
            ),
        ),
        visualmap_opts=opts.VisualMapOpts(
            min_=0, max_=400, 
            orient="horizontal",
            pos_left="center",
            range_color = ['#7fb80e','#f58220','red']
        ),
    )
)
c.render("tmp/客户购买时间分布热力图.html") 
# c.render_notebook()


# 2、客户回购率
# 对客户的购买次数做分组分析
customer = df.groupby(by="customer")['customer'].count().sort_values(ascending=False)  # 进行降序排序
# 构造表格对象
customer_list = []
for i in range(len(customer)):
    customer_list.append([customer.index[i],customer.values[i]])
customer = pd.DataFrame(customer_list,columns=["客户ID","下单次数"])
# 将数据暂存
customer.to_csv("tmp/customer.csv",index=False)
# 数据读取
df_customer = pd.read_csv("tmp/customer.csv")
# 对数据进行分箱处理
customer_cut = pd.cut(  df_customer['下单次数'],
                        bins=[0,2,10,30,60],
                        labels=['流失客户','边缘客户','潜在客户','忠诚客户']
                    )
df_customer['客户类型'] = customer_cut
print(df_customer)

# 画玫瑰图(饼图)
# 数据准备
customer_type_count = df_customer.groupby('客户类型')['客户类型'].count()
list = [[i,int(j)] for i,j in zip(customer_type_count.index.tolist(),customer_type_count.values.tolist())]
list 
c = (
    Pie(init_opts=opts.InitOpts(width="800px", height="600px")) # 设置背景的大小
    .add(
        series_name = "客户占比区间",    # 必须项
        data_pair = list,
        radius=["20%", "50%"],          # 设置环的大小
        # center=["20%", "50%"],        # 设置饼图的位置
        rosetype="radius",              # 设置玫瑰图类型
        label_opts=opts.LabelOpts(
            position="outside",
            formatter="{a|{a}}{abg|}\n{hr|}\n {b|{b}的个数: }{c}个  {per|{d}%}  ",
            background_color="#eee",
            border_color="#aaa",
            border_width=2,
            border_radius=4,
            rich={
                "a": {"color": "#999", "lineHeight": 20, "align": "center"},
                "abg": {
                    "backgroundColor": "#e3e3e3",
                    "width": "100%",
                    "align": "right",
                    "height": 22,
                    "borderRadius": [4, 4, 0, 0],
                },
                "hr": {
                    "borderColor": "#aaa",
                    "width": "100%",
                    "borderWidth": 0.5,
                    "height": 0,
                },
                "b": {"fontSize": 14, "lineHeight": 35},
                "per": {
                    "color": "#eee",
                    "backgroundColor": "#334455",
                    "padding": [2, 5],
                    "borderRadius": 2,
                },
            }
         ) # 设置标签内容格式
        
    )
    .set_colors(["#7fb80e", "#007d65", "#fcaf17", "#FF7256"]) # 颜色设置
    .set_global_opts(title_opts=opts.TitleOpts(title="客户回购次数分类占比"),
                    legend_opts=opts.LegendOpts(
                        pos_top="3%",
                        pos_left="90%",
                        orient='vertical'
                    
                    ),                              # 设置图示的位置
                    )
    
)
c.render("tmp/客户回购次数分类占比.html")
# c.render_notebook()




# 3、折扣百分比和购买商品数量分析
#  可以通过散点图来观察

# 构造散点图数据
total_items_list = df['total_items']
discout_list = df['discount%']
c = (
    Scatter()
    .add_xaxis(xaxis_data=total_items_list)
    .add_yaxis(
        series_name="",
        y_axis=discout_list,
        symbol_size=3,
        label_opts=opts.LabelOpts(is_show=False),
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="折扣百分比和购买商品数量散点图:")
    )
)
c.render("tmp/折扣百分比和购买商品数量散点图.html")



# 4、商品分析
# 构造柱形图数据
x_list = ['非生鲜食物','生鲜类食物','饮料','家用品','美妆类产品','保健类产品','母婴类','宠物用品']
food = round(df['Food%'].mean(),2)
fresh = round(df['Fresh%'].mean(),2)
drinks = round(df['Drinks%'].mean(),2)
home = round(df['Home%'].mean(),2)
beauty = round(df['Beauty%'].mean(),2)
health = round(df['Health%'].mean(),2)
baby = round(df['Baby%'].mean(),2)
pets = round(df['Pets%'].mean(),2)
y_list = [food,fresh,drinks,home,beauty,health,baby,pets]
# 对数据进行排序
x_y_list = [[i,j]for i,j in zip(x_list,y_list)]
x_y_list.sort(key=lambda x : x[1],reverse=False)

x = []
y = []
for i in range(len(x_list)):
    x.append(x_y_list[i][0])
    y.append(x_y_list[i][1])
# 画柱形图

bar = (
    Bar(init_opts=opts.InitOpts(width='800px',height='400px'))
    .add_xaxis(xaxis_data=x)
    .add_yaxis(
        series_name="",
        y_axis=y,
        label_opts=opts.LabelOpts(is_show = False),
        color = 'skyblue',
    )
    .set_global_opts(
        title_opts=opts.TitleOpts("平均购买商品(占总价格百分比):")
    )
    # 反转x和y轴
    .reversal_axis()
)
# bar.render_notebook()
bar.render("tmp/平均购买商品柱状图.html")

# 按周次对商品进行分析
# 对周次和商品进行分组聚合
week_commodity = df.groupby(by='weekday')[['Food%','Fresh%','Drinks%','Home%','Beauty%','Health%','Baby%','Pets%']].mean()

# 创建时间线对象
timeline = Timeline({"theme":ThemeType.LIGHT})

for week in range(len(week_commodity)):
    x_list = ['非生鲜食物','生鲜类食物','饮料','家用品','美妆类产品','保健类产品','母婴类','宠物用品']
    y_list = week_commodity.loc[week+1,:].values
    y_list = [round(j,2) for j in y_list]
    x_y_list = [[i,j]for i,j in zip(x_list,y_list)]
    # 对数据进行排序
    x_y_list.sort(key=lambda x : x[1],reverse=False)
    # 获取最终数据
    x = []
    y = []
    for i in range(len(x_list)):
        x.append(x_y_list[i][0])
        y.append(x_y_list[i][1])
    
    # 构建柱状图对象
    bar = Bar()
    bar.add_xaxis(xaxis_data=x) # 添加x轴数据
    bar.add_yaxis(
        "总价百分比%", 
        y,  # y轴数据
        label_opts=LabelOpts(is_show=False),    # 不显示标签数据
    )
    # 反转x轴和y轴
    bar.reversal_axis()

    # 设置每一周图表的标题
    bar.set_global_opts(
        title_opts=TitleOpts(title=f"周 {week+1} 的商品销售占比")
    )
    # 添加时间轴
    timeline.add(bar,str(week+1))

# 设置自动播放
timeline.add_schema(
    play_interval=2000,     # 自动播放的时间间隔(毫秒)
    is_timeline_show=True,  # 是否在自动播放的时候显示时间线
    is_auto_play=True,      # 是否自动播放
    is_loop_play=False       # 是否循环播放
)

# timeline.render_notebook()
timeline.render("tmp/按周次的商品销售占比时间柱状图.html")



# 5、相关矩阵
# 提取出相关数据
commodity = df[['Food%','Fresh%','Drinks%','Home%','Beauty%','Health%','Baby%','Pets%']]
# 因为其变量比较离散，且属于非线性关系，所有选择斯皮尔曼相关系数
commodity_corr = commodity.corr(method='kendall').round(2)
print(commodity_corr)